# tool.py

import os
import sys
import getopt
import json
import argparse
import math
from tqdm import tqdm
from shutil import copyfile

parser = argparse.ArgumentParser(description='GeoJson文件分析小工具.')
parser.add_argument('-f', help='功能选择 a-统计tag分布(Defalut) s-缺陷文件分离 r-缺陷文件修复', choices=['a', 's', 'r'], default='a')
parser.add_argument('-t', help='统计时筛选tag指定', metavar='Tag', nargs='+')
parser.add_argument('-dist', help='两个坐标之间最小距离', metavar='V', type=float, required=False, default=1.0)
parser.add_argument('-D', help='正常文件处理输出目录', metavar='Path', required=False)
parser.add_argument('-ND', help='缺陷文件处理输出目录', metavar='Path', required=False)
parser.add_argument('-o', help='分析结果输出文件', metavar='Filename', type=argparse.FileType('w', encoding='UTF-8'), required=True)
parser.add_argument('path', help='数据目录', default='.')

def dist_two_point_xy(v1, v2):
    x1 = float(v1[0])
    y1 = float(v1[1])
    x2 = float(v2[0])
    y2 = float(v2[1])

    return math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))

def statistics_all_geojson_files(path):
    """统计路径中所有GeoJson文件路径"""

    file_paths = []

    lsdir = os.listdir(path)
    files = [i for i in lsdir if os.path.isfile(os.path.join(path,i))]
    for f in files:
        file_paths.append(os.path.join(path, f))

    dirs = [i for i in lsdir if os.path.isdir(os.path.join(path,i))]
    for d in dirs:
        file_paths.extend(statistics_all_geojson_files(os.path.join(path, d)))

    return file_paths

def do_tag_statistics(path, outfile, tags):
    """统计tag分布"""

    if not os.path.exists(path) and not os.path.isdir(path):
        parser.print_usage()
        sys.exit(3)

    print("正在统计tag分布...")

    all_json_files = []
    with tqdm(total=1, desc='统计GeoJson文件数目') as pbar:
        all_json_files = statistics_all_geojson_files(path)
        pbar.update(1)

    tag_counts = {}
    error_json_files = []
    with tqdm(total=len(all_json_files), desc='分析Tag') as pbar:
        for f in all_json_files:
            try:
                with open(f, 'r', encoding="UTF-8") as load_f:
                    data = json.load(load_f)

                    tag = data['features'][0]['properties']['type']
            except Exception:
                error_json_files.append(f)
                pbar.update(1)
                continue

            if tags and len(tags) > 0:
                if tag in tags:
                    tag_counts[tag] = tag_counts.get(tag, 0) + 1

                pbar.update(1)
                continue

            tag_counts[tag] = tag_counts.get(tag, 0) + 1
            pbar.update(1)

    

    with tqdm(total=len(tag_counts) + len(error_json_files), desc='写入统计数据') as pbar:
        if len(tag_counts) > 0:
            outfile.write('Tag分布\n')
            for (k, v) in tag_counts.items():
                outfile.write(k + "\t" + str(v) + '\n')
                pbar.update(1)

        if len(error_json_files) > 0:
            outfile.write('加载错误文件列表\n')
            for v in error_json_files:
                outfile.write(v + '\n')
                pbar.update(1)

    print('All Done')

def do_file_separate(path, outfile, min_dist, d_path, nd_path):
    if not os.path.exists(path) and not os.path.isdir(path):
        parser.print_usage()
        sys.exit(3)

    print("正在进行缺陷文件分析...")

    all_json_files = []
    with tqdm(total=1, desc='统计GeoJson文件数目') as pbar:
        all_json_files = statistics_all_geojson_files(path)
        pbar.update(1)

    error_json_files = []
    defect_files = []
    no_defect_files = []
    with tqdm(total=len(all_json_files), desc='缺陷分析') as pbar:
        for f in all_json_files:
            try:
                with open(f, 'r', encoding="UTF-8") as load_f:
                    data = json.load(load_f)
                    geometry = data['features'][0]['geometry']
                    if geometry['type'] != 'MultiLineString':
                        print('只能处理 MultiLineString 类型')
                        sys.exit()
                    points = geometry['coordinates']
            except Exception:
                error_json_files.append(f)
                pbar.update(1)
                continue

            b_defect = False
            for ps in points:
                if len(ps) == 2:
                    break

                index = 1
                while index < len(ps):
                    if dist_two_point_xy(ps[index], ps[index - 1]) >= min_dist:
                        b_defect = True
                        break
                    index += 1

                if b_defect:
                    break

            if b_defect:
                defect_files.append(f)
            else:
                no_defect_files.append(f)
            pbar.update(1)


    with tqdm(total=len(defect_files) + len(error_json_files) + len(no_defect_files), desc='写入统计数据') as pbar:
        if len(defect_files) > 0:
            outfile.write('缺陷文件列表\n')
            for f in defect_files:
                outfile.write(f + '\n')
                pbar.update(1)
            
        if len(no_defect_files) > 0:
            outfile.write('正常文件列表\n')
            for f in no_defect_files:
                outfile.write(f + '\n')
                pbar.update(1)

        if len(error_json_files) > 0:
            outfile.write('加载错误文件列表\n')
            for v in error_json_files:
                outfile.write(v + '\n')
                pbar.update(1)

    if d_path:
        try:
            if not os.path.exists(d_path):
                os.mkdir(d_path)
        except Exception:
            print('输出目录处理失败' + d_path + '\n')
            sys.exit(1)

        with tqdm(total=len(defect_files), desc='拷贝缺陷文件') as pbar:
            for f in defect_files:
                try:
                    f_path = d_path + f[len(path):]
                    copyfile(f, f_path)
                except Exception:
                    print('拷贝文件失败' + f_path + '\n')
                    continue
                pbar.update(1)

    if nd_path:
        try:
            if not os.path.exists(nd_path):
                os.mkdir(nd_path)
        except Exception:
            print('输出目录处理失败' + nd_path + '\n')
            sys.exit(1)

        with tqdm(total=len(no_defect_files), desc='拷贝正常文件') as pbar:
            for f in no_defect_files:
                try:
                    f_path = nd_path + f[len(path):]
                    copyfile(f, f_path)
                except Exception:
                    print('拷贝文件失败' + f_path + '\n')
                    continue
                pbar.update(1)


    print('All Done')

def do_repaire(path, outfile, min_dist, d_path):
    print("请联系作者 19983156842 516327203@qq.com获取全部功能")
    return

def main():
    args = parser.parse_args()

    if args.f == 's':
        do_file_separate(args.path, args.o, args.dist, args.D, args.ND)
    elif args.f == 'r':
        if not args.D:
            parser.print_usage()
            print('选择缺陷文件修复功能时必须指定-D')
            return

        do_repaire(args.path, args.o, args.dist, args.D)
    else:
        do_tag_statistics(args.path, args.o, args.t)

if __name__ == '__main__':
    main()